import type { RequestIntervalCanResult, RequestIntervalRecord } from './request_interval'
import { logger, pageWindow } from '../../../types/constants'
import { SYMBOLS } from '../../../types/interfaces'
import { TimerManager } from '../../timer_manager'
import { ToolKit } from '../../utils/toolkit'
import { RequestInterval } from './request_interval'

/**
 * 请求类型枚举
 */
export enum RequestType {
  JSON = 'json', // 优先使用：安全、现代
  JSONP = 'jsonp', // 备用方案：兼容老系统
  AUTO = 'auto', // 自动选择：优先 JSON，失败降级 JSONP
}

/**
 * 请求配置接口
 */
export interface RequestConfig {
  useGM?: boolean // 是否使用 GM_xmlhttpRequest（默认自动检测）
  requestId?: number // 请求 ID（内部使用）
  requestType?: RequestType // 请求类型

  enableCache?: boolean // 是否启用请求缓存
  forceRefresh?: boolean // 是否强制刷新缓存
  maxCacheSize?: number // 最大缓存大小

  timeout?: number // 超时时间（毫秒）
  minInterval?: number // 最小请求间隔（毫秒）
  retryCount?: number // 重试次数

  signal?: AbortSignal | null // 取消信号
  cleanup?: boolean // 是否自动清理资源

  // AUTO 模式
  retryOnFail?: boolean // 失败时是否重试

  // JSON 模式
  fallbackToJSONP?: boolean // 是否允许降级到 JSONP

  // JSONP 模式
  callbackParam?: string // 回调参数名
  callbackName?: string // 自定义回调函数名
}

/**
 * 请求响应接口
 */
export interface RequestBaseResponse {
  requestId: number // 请求 ID
  requestType: RequestType // 实际使用的请求类型
  cached?: boolean // 是否使用了缓存响应
  usedFallback: boolean // 是否使用了降级方案
  retryCount: number // 实际重试次数
  duration: number // 请求耗时（毫秒）
}
export interface RequestSuccessResponse<T = any> extends RequestBaseResponse {
  data: T // 响应数据
  status: 'success'
  error?: never
}
export interface RequestErrorResponse<T = any> extends RequestBaseResponse {
  url: string
  status: 'error'
  error: RequestError
  data?: T // 失败时可能仍有缓存数据
}

export interface RequestCachedResponse<T = any> extends RequestBaseResponse {
  status: 'cached'
  data: T
  error?: never
  cacheSource: 'memory' | 'persistent' | 'network' // 缓存来源
  cacheHitType: 'exact' | 'stale' | 'fallback' // 缓存命中类型
}
export type RequestResponse<T = any> = RequestSuccessResponse<T> | RequestErrorResponse<T> | RequestCachedResponse<T>

/**
 * 错误元数据接口
 */
interface ErrorMetadata {
  url: string
  requestId: number
  requestType: RequestType
}

export enum RequestErrorType {
  TIMEOUT = 'timeout',
  NETWORK = 'network',
  ABORT = 'abort',
  PARSE = 'parse',
  VALIDATION = 'validation',
  CORS = 'cors',
  PERMISSION = 'permission',
  UNKNOWN = 'unknown',
}

/**
 * 请求错误接口
 */
export interface RequestError extends ErrorMetadata {
  type: RequestErrorType
  message: string // 错误信息
}

/**
 * URL 验证结果接口
 */
export interface RequestValidationResult {
  isValid: boolean
  error?: RequestError
}

/**
 * 请求引擎
 */
export enum RequestEngine {
  GM = 'gm',
  SCRIPT = 'script',
  FETCH = 'fetch',
}

export class RequestHandler {
  private readonly name: string = 'RequestHandler'
  static instance: RequestHandler | null = null
  private readonly timerManager: TimerManager = TimerManager.getInstance()
  private readonly intervalManager: RequestInterval = RequestInterval.getInstance()
  private readonly DEFAULT_CONFIG = {
    requestType: RequestType.AUTO,
    enableCache: false, // 不启用请求缓存
    forceRefresh: false, // 不强制刷新缓存
    maxCacheSize: 100,
    timeout: 1000,
    minInterval: 1000, // 最小请求间隔
    callbackParam: 'callback',
  }

  private requestCount = 0 // 请求计数器
  private activeRequests: Map<number, {
    abort?: () => void
    engine: RequestEngine
    requestType: RequestType
  }> = new Map()

  static getInstance(): RequestHandler {
    if (!RequestHandler.instance) {
      RequestHandler.instance = new RequestHandler()
    }
    return RequestHandler.instance
  }

  /**
   * 发起请求（智能选择模式）- 优先使用安全的 JSON 请求，失败时降级到 JSONP
   */
  async request<T = any>(url: string, config: RequestConfig = {}): Promise<RequestResponse<T>> {
    const startTime = Date.now()
    const requestId = config.requestId || this.generateRequestId()
    const finalConfig = this.getMergedConfig(config, requestId)
    const { retryCount } = finalConfig

    // 检查取消信号
    if (finalConfig.signal?.aborted)
      throw ToolKit.error.createAbortError(`请求 #${requestId} 已被取消`)

    // 添加取消监听
    if (finalConfig.signal) {
      finalConfig.signal.addEventListener('abort', () => {
        this.cancelRequest(finalConfig.requestId)
      })
    }

    logger.debug(`[${this.name}] 开始请求 #${requestId}`, {
      url,
      requestType: finalConfig.requestType,
      useGM: finalConfig.useGM,
    })

    try {
      // 检查缓存（在请求间隔检查之前）
      if (finalConfig.enableCache && !finalConfig.forceRefresh) {
        const cachedResponse = this.intervalManager.getCachedResponse<T>(url, finalConfig)
        if (cachedResponse) {
          logger.info(`[${this.name}] ${SYMBOLS.UI.BULLSEYE} 使用缓存响应`, { url })
          return this.createCachedResponse<T>(cachedResponse, requestId, finalConfig.requestType)
        }
      }

      // 检查请求间隔
      const intervalCheck = this.checkRequestInterval(url, finalConfig)
      if (!intervalCheck.canRequest) {
        logger.debug(`[${this.name}] 请求频率限制，等待 ${intervalCheck.waitTime}ms`, {
          url,
          waitTime: intervalCheck.waitTime,
        })

        // 如果有缓存且允许使用缓存
        const cachedResponse = this.intervalManager.getCachedResponse<T>(url, finalConfig)
        if (finalConfig.enableCache && cachedResponse) {
          logger.info(`[${this.name}] ${SYMBOLS.UI.BULLSEYE} 使用缓存响应`, { url })
          return this.createCachedResponse<T>(cachedResponse, requestId, finalConfig.requestType)
        }

        // 等待间隔时间
        if (intervalCheck.waitTime > 0)
          await ToolKit.async.delay(intervalCheck.waitTime)
      }

      // 记录请求开始
      this.intervalManager.recordRequestStart(url, finalConfig)

      let result: RequestResponse<T>
      let usedFallback = false

      switch (finalConfig.requestType) {
        case RequestType.JSON:
          result = await this.requestWithJSON<T>(url, finalConfig)
          break

        case RequestType.JSONP:
          result = await this.requestWithJSONP<T>(url, finalConfig)
          break

        case RequestType.AUTO:
        default:
          // 自动模式：优先 JSON，失败降级 JSONP
          try {
            result = await this.requestWithJSON<T>(url, finalConfig)
          }
          catch (error) {
            if (this.shouldFallbackToJSONP(error, finalConfig)) {
              logger.notice(`[${this.name}] ${SYMBOLS.STATUS.WARNING} JSON 请求失败，降级到 JSONP`, error)
              result = await this.requestWithJSONP<T>(url, finalConfig)
              usedFallback = true
            }
            else {
              throw error
            }
          }
          break
      }

      // 记录请求成功
      if (result.status === 'success') {
        this.intervalManager.recordRequestSuccess(url, finalConfig, result.data)
      }
      else if (result.status === 'cached') {
      // 缓存响应不需要重复记录
      }
      else {
        this.intervalManager.recordRequestError(url, result.error)
      }

      return {
        ...result,
        requestId,
        usedFallback,
      }
    }
    catch (error) {
      // 重试机制
      if (retryCount > 0)
        await this.retryRequest(url, retryCount, finalConfig)

      const duration = Date.now() - startTime

      // 尝试使用缓存作为降级方案
      let fallbackData: T | null = null
      if (finalConfig.enableCache) {
        fallbackData = this.intervalManager.getCachedResponse<T>(url, finalConfig)
        if (fallbackData) {
          logger.info(`[${this.name}] ${SYMBOLS.UI.BULLSEYE} 请求失败，使用缓存数据作为降级方案`, { url })
        }
      }

      // 记录请求失败
      this.intervalManager.recordRequestError(url, error as RequestError)

      return this.createErrorResponse<T>(error as RequestError, {
        url,
        requestId,
        requestType: finalConfig.requestType,
        duration,
        usedFallback: !!fallbackData,
        fallbackData, // 传递降级数据
      })
    }
  }

  /**
   * 使用安全的 JSON 请求（推荐首选）
   */
  private async requestWithJSON<T = any>(url: string, config: Required<RequestConfig>): Promise<RequestResponse<T>> {
    const requestId = config.requestId

    logger.debug(`[${this.name}] 开始 JSON 请求 #${requestId}`)

    // 优先使用 GM_xmlhttpRequest
    if (config.useGM)
      return this.requestWithGM<T>(url, config, RequestType.JSON)

    // 使用 Fetch API
    return this.requestWithFetch<T>(url, config)
  }

  /**
   * 发起 JSONP 请求（智能选择模式）- 仅用于简单的 GET 请求，不适合大数据传输，适合处理跨域
   */
  private async requestWithJSONP<T = any>(url: string, config: Required<RequestConfig>): Promise<RequestResponse<T>> {
    const useGM = this.shouldUseGM(config)
    return useGM
      ? this.requestWithGM<T>(url, config, RequestType.JSONP)
      : this.requestWithScript<T>(url, config)
  }

  /**
   * 使用 GM_xmlhttpRequest 发起请求（绕过CSP）
   */
  private requestWithGM<T = any>(url: string, config: Required<RequestConfig>, requestType: RequestType): Promise<RequestResponse<T>> {
    return new Promise((resolve, reject) => {
      const { timeout, callbackParam, callbackName, requestId: configRequestId } = config
      const startTime = Date.now()
      const requestId = configRequestId
      const engine = RequestEngine.GM

      // 1. 创建清理函数
      const cleanup = this.createCleanupFunction(requestId)

      // 2. 检查取消信息
      const abort = this.setupAbortRequestListener(config, reject, cleanup)

      // 3. 验证 URL
      if (!this.validateUrlForRequest(url, requestId, requestType, reject))
        return

      // 4. 构建完整的 URL
      const finalUrl = requestType === RequestType.JSONP
        ? ToolKit.browser.url.buildUrlParam(url, callbackParam, callbackName)
        : url

      logger.debug(`[${this.name}] 开始发起 GM 请求 #${requestId}: ${finalUrl}`, config)

      // 5. 设置超时定时器
      this.createTimeoutHandler(
        requestId,
        timeout,
        url,
        cleanup,
        reject,
        requestType,
      )

      const error_metadata = {
        url,
        requestId,
        requestType,
      }

      const request = GM_xmlhttpRequest({
        method: 'GET',
        url: finalUrl,
        timeout,
        responseType: requestType === RequestType.JSON ? 'json' : undefined,
        onload: (response) => {
          abort?.()
          cleanup()
          const duration = Date.now() - startTime

          if (response.status >= 200 && response.status < 300) {
            try {
              const data = requestType === RequestType.JSONP
                ? this.parseJSONPResponse<T>(response.responseText, callbackName)
                : this.parseJSONResponse<T>(response.responseText)

              const successResponse = this.createSuccessResponse(data, {
                duration,
                requestId,
                requestType,
                usedFallback: false,
              })
              resolve(successResponse)
            }
            catch (parseError) {
              reject(this.createError(RequestErrorType.PARSE, `响应解析失败: ${ToolKit.error.getMessage(parseError)}`, error_metadata))
            }
          }
          else {
            reject(this.createError(RequestErrorType.NETWORK, `HTTP ${response.status}: ${response.statusText}`, error_metadata))
          }
        },
        onerror: (error) => {
          abort?.()
          cleanup()

          if (ToolKit.error.isPermission(error.error))
            reject(this.createError(RequestErrorType.PERMISSION, `权限错误：未将域名添加到用户域名白名单中`, error_metadata))

          reject(this.createError(RequestErrorType.NETWORK, `网络错误: ${error.error}`, error_metadata))
        },
        ontimeout: () => {
          cleanup()
          reject(this.createError(RequestErrorType.TIMEOUT, `请求超时 (${timeout}ms)`, error_metadata))
        },
        onabort: () => {
          abort?.()
          cleanup()
          reject(this.createError(RequestErrorType.ABORT, '请求被中止', error_metadata))
        },
      })

      // 存储请求
      this.activeRequests.set(requestId, {
        abort: () => {
          request.abort()
          abort?.()
          cleanup()
        },
        engine,
        requestType,
      })
    })
  }

  /**
   * 使用 Fetch API 发起 JSON 请求
   */
  private async requestWithFetch<T = any>(url: string, config: Required<RequestConfig>): Promise<RequestResponse<T>> {
    return new Promise((resolve, reject) => {
      const { timeout, requestId: configRequestId } = config
      const requestId = configRequestId
      const startTime = Date.now()
      const engine = RequestEngine.FETCH

      // 验证URL
      if (!this.validateUrlForJSONRequest(url, requestId))
        return

      const error_metadata = {
        url,
        requestId,
        requestType: RequestType.JSON,
      }

      const controller = new AbortController()
      const timeoutId = setTimeout(() => {
        controller.abort()
        reject(this.createError(RequestErrorType.TIMEOUT, `请求超时 (${timeout}ms)`, error_metadata))
      }, timeout)

      fetch(url, {
        method: 'GET',
        signal: controller.signal,
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json',
        },
      })
        .then(async (response) => {
          clearTimeout(timeoutId)

          if (!response.ok) {
            // 检查是否为 CORS 错误
            if (response.type === 'opaque') {
              reject(this.createError(RequestErrorType.CORS, 'CORS 策略阻止了请求', error_metadata))
              return
            }
            reject(this.createError(RequestErrorType.NETWORK, `HTTP ${response.status}: ${response.statusText}`, error_metadata))
            return
          }

          try {
            const data = await response.json()
            const duration = Date.now() - startTime

            const successResponse = this.createSuccessResponse(data, {
              duration,
              requestId,
              requestType: RequestType.JSON,
              usedFallback: false,
            })
            resolve(successResponse)
          }
          catch (parseError) {
            reject(this.createError(RequestErrorType.PARSE, `JSON 解析失败: ${ToolKit.error.getMessage(parseError)}`, error_metadata))
          }
        })
        .catch((error) => {
          clearTimeout(timeoutId)
          if (error.name === 'AbortError') {
            reject(this.createError(RequestErrorType.TIMEOUT, `请求超时 (${config.timeout}ms)`, error_metadata))
          }
          else {
            reject(this.createError(RequestErrorType.NETWORK, `网络错误: ${error.message}`, error_metadata))
          }
        })

      // 存储请求用于取消
      this.activeRequests.set(requestId, {
        abort: () => controller.abort(),
        engine,
        requestType: RequestType.JSON,
      })
    })
  }

  /**
   * 使用 Script 标签发起 JSONP 请求
   * @template T - 响应数据类型
   * @param url - 请求 URL
   * @param  config - 请求配置
   * @returns 返回 Promise
   * @example
   * const result = await JSONPToolkit.request<IHitokotoData>('https://v1.hitokoto.cn');
   * console.log(result.data.hitokoto);
   */
  requestWithScript<T = any>(url: string, config: Required<RequestConfig>): Promise<RequestResponse<T>> {
    return new Promise((resolve, reject) => {
      const { timeout, callbackParam, callbackName } = config
      const startTime = Date.now()
      const requestId = config.requestId
      const engine = RequestEngine.SCRIPT

      // 验证 URL
      if (!this.validateUrlForRequest(url, requestId, RequestType.JSONP, reject))
        return

      const finalUrl = ToolKit.browser.url.buildUrlParam(url, callbackParam, callbackName)
      const script = document.createElement('script')

      script.src = finalUrl
      script.id = `jsonp_script_${requestId}`
      script.defer = true // 延迟执行，不阻塞渲染
      script.crossOrigin = 'anonymous' // 跨域请求
      script.referrerPolicy = 'no-referrer' // 不发送 referrer 信息
      script.fetchPriority = 'low' // 低优先级加载（现代浏览器）

      // 创建清理函数
      const cleanup = this.createCleanupFunction(requestId, callbackName, script)

      // 设置超时定时器
      this.createTimeoutHandler(
        requestId,
        timeout,
        url,
        cleanup,
        reject,
        RequestType.JSONP,
      )

      // 定义回调函数
      pageWindow[callbackName] = (data: T) => {
        cleanup()
        const duration = Date.now() - startTime
        const successResponse = this.createSuccessResponse(data, {
          duration,
          requestId,
          requestType: RequestType.JSONP,
          usedFallback: false,
        })
        resolve(successResponse)
      }

      const error_metadata = {
        url,
        requestId,
        requestType: RequestType.JSONP,
      }

      // 错误处理
      script.onerror = () => {
        cleanup()
        reject(this.createError(RequestErrorType.NETWORK, '网络请求失败', error_metadata))
      }

      script.onabort = () => {
        cleanup()
        reject(this.createError(RequestErrorType.ABORT, '请求被中止', error_metadata))
      }

      // 存储活跃请求信息
      this.activeRequests.set(requestId, {
        abort: () => cleanup(),
        engine,
        requestType: RequestType.JSONP,
      })

      // 添加到 DOM
      document.head.appendChild(script)
    })
  }

  /**
   * 批量发起请求
   */
  async batchRequest<T = any>(
    urls: string[],
    config: RequestConfig = {},
  ): Promise<Array<RequestResponse<T>>> {
    if (!Array.isArray(urls) || urls.length === 0) {
      throw new Error('URL 列表不能为空')
    }

    const results: Array<RequestResponse<T>> = []
    const useGM = this.shouldUseGM(config)

    logger.info(`[${this.name}] ${SYMBOLS.UI.PACKAGE} 开始批量请求`, {
      total: urls.length,
      engine: useGM ? 'GM_xmlhttpRequest' : 'Script Tag',
    })

    const baseRequestId = this.requestCount + 1
    this.requestCount += urls.length // 提前分配 ID 范围

    for (let i = 0; i < urls.length; i++) {
      const requestId = baseRequestId + i
      const url = urls[i]

      try {
        // 为每个请求分配唯一的 requestId
        const result = await this.request<T>(url, {
          ...config,
          requestId,
        })
        results.push(result)

        if (result.status === 'success' || result.status === 'cached') {
          logger.debug(`[${this.name}] ${SYMBOLS.STATUS.SUCCESS} 请求成功`, {
            url,
            requestId,
            duration: `${result.duration}ms`,
            cached: result.status === 'cached',
          })
        }
        else {
          logger.warn(`[${this.name}] 请求失败`, {
            url,
            requestId,
            error: result.error,
          })
        }
      }
      catch (error) {
        // 创建错误响应而不是抛出异常
        const errorResponse: RequestErrorResponse = this.createErrorResponse(
          error as RequestError,
          {
            url,
            requestId,
            requestType: config.requestType || RequestType.AUTO,
            duration: 0,
            usedFallback: false,
            fallbackData: null,
          },
        )
        results.push(errorResponse)
        logger.warn(`[${this.name}] 请求异常`, {
          url,
          requestId,
          error,
        })
      }

      // 批次间延迟
      if (i < urls.length - 1) {
        await ToolKit.async.delay(200)
      }
    }

    const successCount = results.filter(r =>
      r.status === 'success' || r.status === 'cached',
    ).length

    logger.info(`[${this.name}] ${SYMBOLS.UI.BULLSEYE} 批量请求完成`, {
      total: results.length,
      success: successCount,
      failed: results.length - successCount,
      successRate: `${((successCount / results.length) * 100).toFixed(1)}%`,
    })

    return results
  }

  /**
   * 带重试的请求
   */
  async retryRequest<T = any>(
    url: string,
    maxRetries: number = 3,
    config: RequestConfig = {},
  ): Promise<RequestResponse<T>> {
    // 为整个重试会话生成基础 ID
    const baseRequestId = this.generateRequestId()

    logger.debug(`[${this.name}] ${SYMBOLS.STATUS.REFRESH} 开始重试请求`, { url, maxRetries, baseRequestId })

    for (let attempt = 1; attempt <= maxRetries; attempt++) {
      // 为每次尝试生成子 ID
      const attemptRequestId = baseRequestId + (attempt * 0.1) // 使用小数区分尝试
      const attemptConfig = {
        ...config,
        requestId: Math.floor(attemptRequestId), // 使用整数部分作为主要 ID
        timeout: (config.timeout || this.DEFAULT_CONFIG.timeout) * attempt,
      }

      try {
        const result = await this.request<T>(url, attemptConfig)

        // 检查响应状态
        if (result.status === 'success' || result.status === 'cached') {
          logger.info(`[${this.name}] ${SYMBOLS.STATUS.SUCCESS} 第 ${attempt} 次尝试成功`, {
            url,
            cached: result.status === 'cached',
            requestId: result.requestId,
            retryCount: attempt,
            duration: `${result.duration}ms`,
          })
          return {
            ...result,
            retryCount: attempt,
          }
        }
        else {
          // 请求失败但有缓存数据
          if (result.data) {
            logger.warn(`[${this.name}] ${SYMBOLS.STATUS.WARNING} 第 ${attempt} 次尝试失败，但使用缓存数据`, {
              url,
              error: result.error,
              requestId: result.requestId,
              retryCount: attempt,
            })
            return {
              ...result,
              retryCount: attempt,
            }
          }

          throw new Error(result.error.message)
        }
      }
      catch (error) {
        if (attempt === maxRetries) {
          logger.error(`[${this.name}] ${SYMBOLS.STATUS.ERROR} 重试请求最终失败`, {
            url,
            attempt,
            maxRetries,
            baseRequestId,
            error,
          })

          // 返回错误响应而不是抛出异常
          return this.createErrorResponse<T>(error as RequestError, {
            url,
            requestId: Math.floor(baseRequestId + (maxRetries * 0.1)),
            requestType: config.requestType || RequestType.AUTO,
            usedFallback: false,
            fallbackData: null,
            retryCount: attempt,
            duration: 0,
          })
        }

        // 指数退避策略
        const delayTime = Math.min(2 ** (attempt - 1) * 1000, 10000)
        logger.warn(`[${this.name}] 第 ${attempt} 次尝试失败，${delayTime}ms后重试`, {
          url,
          requestId: Math.floor(attemptRequestId),
          error,
          nextDelay: `${delayTime}ms`,
        })

        await ToolKit.async.delay(delayTime)
      }
    }

    // 永远不会执行到这里，但为了类型安全
    throw new Error(`重试逻辑异常`)
  }

  /**
   * 判断是否应该降级到 JSONP 请求
   */
  private shouldFallbackToJSONP(error: any, config: Required<RequestConfig>): boolean {
    if (!config.fallbackToJSONP && config.requestType !== RequestType.AUTO)
      return false

    const errorTypes = ToolKit.error.checkErrorTypes(error)
    const { cors, network, timeout } = errorTypes
    return cors || network || timeout
  }

  /**
   * 智能选择请求模式
   */
  private shouldUseGM(config: RequestConfig): boolean {
    // 如果明确指定了 useGM，则使用该设置
    if (config.useGM !== undefined)
      return config.useGM

    // 自动检测：在油猴环境中优先使用 GM_xmlhttpRequest
    return ToolKit.environment.isGMXMLHttpRequestAvailable()
  }

  /**
   * 检查请求间隔
   */
  private checkRequestInterval(url: string, config: Required<RequestConfig>): RequestIntervalCanResult {
    const minInterval = config.minInterval || this.DEFAULT_CONFIG.minInterval

    // 临时设置最小间隔进行检查
    const checkResult = this.intervalManager.canRequest(url)

    if (!checkResult.canRequest && checkResult.waitTime > minInterval) {
      return {
        canRequest: false,
        waitTime: checkResult.waitTime,
        record: checkResult.record,
      }
    }

    return { canRequest: true, waitTime: 0 }
  }

  /**
   * 生成唯一的请求 ID
   */
  private generateRequestId(): number {
    return ++this.requestCount
  }

  /**
   * 获取合并后的配置
   */
  private getMergedConfig(config: RequestConfig, requestId: number): Required<RequestConfig> {
    return {
      useGM: config.useGM !== undefined ? config.useGM && ToolKit.environment.isGMXMLHttpRequestAvailable() : false,
      requestId,
      requestType: config.requestType || this.DEFAULT_CONFIG.requestType,
      enableCache: config.enableCache || this.DEFAULT_CONFIG.enableCache,
      forceRefresh: config.forceRefresh || this.DEFAULT_CONFIG.forceRefresh,
      maxCacheSize: config.maxCacheSize || this.DEFAULT_CONFIG.maxCacheSize,
      timeout: config.timeout || this.DEFAULT_CONFIG.timeout,
      minInterval: config.minInterval || this.DEFAULT_CONFIG.minInterval,
      retryCount: config.retryCount || (config.retryOnFail ? 0 : 1),
      retryOnFail: config.retryOnFail ?? (config?.retryCount || 0) > 0,
      signal: config.signal || null,
      cleanup: config.cleanup !== false, // 默认自动清理
      callbackParam: config.callbackParam || this.DEFAULT_CONFIG.callbackParam,
      callbackName: config.callbackName || this.generateCallbackName(requestId),
      fallbackToJSONP: config.fallbackToJSONP !== false,
    }
  }

  /**
   * 通用 URL 验证
   */
  private validateUrlForRequest(
    url: string,
    requestId: number,
    requestType: RequestType,
    reject: (error: RequestError) => void,
  ): boolean {
    const validation = requestType === RequestType.JSON
      ? this.validateUrlForJSONRequest(url, requestId)
      : this.validateUrlForJSONPRequest(url, requestId)

    if (!validation.isValid && validation.error) {
      reject(validation.error)
      return false
    }
    return true
  }

  /**
   * 验证 JSON 请求 URL
   */
  private validateUrlForJSONRequest(url: string, requestId: number): RequestValidationResult {
    const error_metadata = {
      url,
      requestId,
      requestType: RequestType.JSON,
    }
    if (!url || url.trim().length === 0) {
      return {
        isValid: false,
        error: this.createError(RequestErrorType.VALIDATION, 'URL 不能为空', error_metadata),
      }
    }

    try {
      void new URL(url)
      return { isValid: true }
    }
    catch {
      return {
        isValid: false,
        error: this.createError(RequestErrorType.VALIDATION, 'URL 格式无效', error_metadata),
      }
    }
  }

  /**
   * 验证 JSONP 请求 URL
   */
  private validateUrlForJSONPRequest(url: string, requestId: number): RequestValidationResult {
    const error_metadata = {
      url,
      requestId,
      requestType: RequestType.JSONP,
    }

    if (!url || url.trim().length === 0) {
      return {
        isValid: false,
        error: this.createError(RequestErrorType.VALIDATION, 'URL 不能为空', error_metadata),
      }
    }

    try {
      // 先验证URL格式
      void new URL(url)

      // 再验证协议
      if (!this.isValidJSONPUrl(url)) {
        return {
          isValid: false,
          error: this.createError(RequestErrorType.VALIDATION, 'URL 协议必须是 HTTP 或 HTTPS', error_metadata),
        }
      }
      return { isValid: true }
    }
    catch {
      return {
        isValid: false,
        error: this.createError(RequestErrorType.VALIDATION, 'URL 格式无效', error_metadata),
      }
    }
  }

  /**
   * 创建清理函数
   */
  private createCleanupFunction(
    requestId: number,
    callbackName?: string,
    script?: HTMLScriptElement,
  ): () => void {
    return () => {
      // 清理全局回调函数
      try {
        if (callbackName && pageWindow[callbackName]) {
          delete pageWindow[callbackName]
        }
      }
      catch (error) {
        logger.debug(`[${this.name}] 清理回调函数异常`, error)
      }

      // 清理 script 标签
      if (script && script.parentNode) {
        script.parentNode.removeChild(script)
      }

      // 从活跃请求中移除
      this.activeRequests.delete(requestId)
    }
  }

  /**
   * 创建超时处理器
   */
  private createTimeoutHandler(
    requestId: number,
    timeout: number,
    url: string,
    cleanup: () => void,
    reject: (error: RequestError) => void,
    requestType: RequestType,
  ): string {
    const timeoutTaskId = `jsonp-timeout-${requestId}`

    this.timerManager.createTimerTask({
      id: timeoutTaskId,
      delay: timeout,
      callback: () => {
        cleanup()
        reject(this.createError(RequestErrorType.TIMEOUT, `请求超时 (${timeout}ms)`, { url, requestId, requestType }))
      },
    })

    return timeoutTaskId
  }

  /**
   * 解析 JSONP 响应
   */
  private parseJSONPResponse<T>(responseText: string, callbackName: string): T {
    const cleanText = responseText.trim()

    const jsonpPatterns = [
      // 格式1: ;callback({...})
      new RegExp(`^;${callbackName}\\((.+)\\)(;)?$`, 's'),
      // 格式2: callback({...})
      new RegExp(`^${callbackName}\\((.+)\\)(;)?$`, 's'),
      // 格式3: callback({...});
      new RegExp(`^${callbackName}\\((.+)\\);$`, 's'),
      // 格式4: ;callback({...});
      new RegExp(`^;${callbackName}\\((.+)\\);$`, 's'),
      // 格式5: 可能有多余空格 callback ( {...} )
      new RegExp(`^\\s*;?\\s*${callbackName}\\s*\\((.+)\\)\\s*;?\\s*$`, 's'),
    ]

    // 尝试所有可能的模式
    for (const pattern of jsonpPatterns) {
      const match = cleanText.match(pattern)
      if (match && match[1]) {
        try {
          logger.debug(`${this.name}] 匹配到 JSONP 格式:`, pattern.toString())
          let jsonContent = match[1].trim()

          // 移除最外层的引号
          if (jsonContent.startsWith('"') && jsonContent.endsWith('"')) {
            jsonContent = jsonContent.slice(1, -1)
          }

          // 处理转义字符
          const unescapedContent = jsonContent
            .replace(/\\"/g, '"') // 将 \" 替换为 "
            .replace(/\\\\/g, '\\') // 将 \\ 替换为 \

          const jsonData = JSON.parse(unescapedContent)
          logger.debug(`${this.name}] JSON 解析成功`, jsonData)

          return jsonData
        }
        catch (error) {
          logger.debug(`[${this.name}] JSON 解析失败，尝试下一个模式`, error)
        }
      }
    }

    // 如果所有模式都失败，尝试直接解析为 JSON
    try {
      logger.debug(`${this.name}] 尝试直接解析为 JSON`)
      const directData = JSON.parse(cleanText)
      logger.debug(`${this.name}] 直接 JSON 解析成功`, directData)
      return directData
    }
    catch {
      throw new Error('无效的 JSONP 响应格式')
    }
  }

  /**
   * 解析 JSON 响应
   */
  private parseJSONResponse<T>(responseText: string): T {
    const cleanText = responseText.trim()
    try {
      return JSON.parse(cleanText)
    }
    catch {
      throw new Error('无效的 JSON 响应格式')
    }
  }

  /**
   * 验证 URL 是否支持 JSONP 请求
   * @param url - 待验证的 URL
   * @returns {boolean} 是否支持 JSONP
   * @private
   */
  private isValidJSONPUrl(url: string): boolean {
    try {
      const urlObj = new URL(url)
      // 检查是否为 HTTP/HTTPS 协议
      return ['http:', 'https:'].includes(urlObj.protocol)
    }
    catch {
      return false
    }
  }

  /**
   * 生成唯一的回调函数名
   * @param {number} requestId - 请求ID
   * @returns {string} 回调函数名
   */
  private generateCallbackName(requestId: number): string {
    return ToolKit.string.generateUniqueId({ prefix: `jsonp_callback_${requestId}`, separator: 'underscore', withTime: false })
  }

  /**
   * 创建错误对象
   */
  private createError(type: RequestError['type'], message: string, metadata: ErrorMetadata): RequestError {
    return {
      type,
      message: `${message}`,
      ...metadata,
    }
  }

  private createSuccessResponse<T>(
    data: T,
    metadata: {
      duration: number
      requestId: number
      requestType: RequestType
      usedFallback: boolean
    },
  ): RequestSuccessResponse<T> {
    return {
      status: 'success',
      data,
      retryCount: 0,
      ...metadata,
    }
  }

  /**
   * 创建缓存响应
   */
  private createCachedResponse<T>(
    data: T,
    requestId: number,
    requestType: RequestType,
  ): RequestCachedResponse<T> {
    return {
      status: 'cached',
      cached: true, //  标记为缓存响应
      cacheSource: 'memory', // 添加缓存来源
      cacheHitType: 'exact', // 添加缓存命中类型
      data,
      requestId,
      requestType,
      usedFallback: false,
      retryCount: 0,
      duration: 0, // 缓存响应没有耗时
    }
  }

  /**
   * 创建错误响应（而不是抛出异常）
   */
  private createErrorResponse<T>(
    error: RequestError,
    metadata: {
      url: string
      requestId: number
      requestType: RequestType
      usedFallback: boolean
      fallbackData: T | null
      retryCount?: number
      duration: number
    },
  ): RequestErrorResponse<T> {
    return {
      status: 'error',
      error,
      data: metadata.fallbackData ?? undefined,
      retryCount: metadata.retryCount ?? 0,
      ...metadata,
    }
  }

  /**
   * 获取当前请求计数
   */
  getRequestCount(): number {
    return this.requestCount
  }

  /**
   * 获取活跃请求数量
   */
  getActiveRequestCount(): number {
    return this.activeRequests.size
  }

  /**
   * 获取请求统计信息
   */
  getRequestStats(url: string): RequestIntervalRecord | null {
    return this.intervalManager.getUrlStats(url)
  }

  /**
   * 清除特定 URL 的缓存
   */
  clearUrlCache(url: string): boolean {
    return this.intervalManager.clearUrlRecord(url)
  }

  /**
   * 获取所有请求统计
   */
  getAllRequestStats(): Array<{ url: string, stats: RequestIntervalRecord }> {
    return this.intervalManager.getAllStats()
  }

  /**
   * 取消指定请求
   * @param requestId - 请求 ID
   * @returns {boolean} 是否取消成功
   */
  cancelRequest(requestId: number): boolean {
    const request = this.activeRequests.get(requestId)

    if (request) {
      request.abort?.()
      logger.info(`[${this.name}] ${SYMBOLS.OTHERS.STOP} 取消请求 #${requestId}`)
      return true
    }

    return false
  }

  /**
   * 设置请求取消监听
   */
  setupAbortRequestListener(config: RequestConfig, reject: (reason?: any) => void, callback?: () => void): (() => void) | undefined {
    // 如果信号已中止，立即拒绝
    if (config.signal?.aborted) {
      callback?.()
      reject(ToolKit.error.createAbortError('请求已被取消'))
      return undefined
    }

    // 如果没有信号，返回 undefined
    if (!config.signal)
      return undefined

    // 定义取消处理函数
    const onAbort = () => {
      callback?.()
      reject(ToolKit.error.createAbortError('请求已被取消'))
    }

    // 添加事件监听
    config.signal.addEventListener('abort', onAbort)

    // 返回清理函数
    return () => {
      config.signal?.removeEventListener('abort', onAbort)
    }
  }

  /**
   * 清理所有请求相关资源（用于页面卸载时调用）
   */
  cleanupAll(): void {
    const count = this.activeRequests.size
    this.activeRequests.forEach((_, requestId) => {
      this.cancelRequest(requestId)
    })
    this.activeRequests.clear()

    logger.info(`[${this.name}] ${SYMBOLS.OTHERS.CLEAR} 清理所有资源`, { cleanedCount: count })
  }
}
